
module Main where

import Text.Printf -- Oba, Haskell tem printf! :-)

type Point     = (Float,Float)
type Color     = (Int,Int,Int)
type Circle    = (Point,Float)

imageWidth :: Int
imageWidth = 1920

imageHeight :: Int
imageHeight = 1080


-- Funcao principal que faz leitura do dataset e gera arquivo SVG
main :: IO ()
main = do
        strcontent <- readFile infile
        let pairs = map (span (/= ' ')) (lines strcontent)
            freqs = readInts (map snd pairs)
        writeFile outfile (svgCloudGen imageWidth imageHeight freqs)
        putStrLn "Ok!"
        where
                infile = "dataset.txt"
                outfile = "tagcloud.svg"


-- Transforma lista de strings em lista de inteiros
readInts :: [String] -> [Int]
readInts ss = map read ss



-- Gera o documento SVG da tag cloud, concatenando cabecalho, conteudo e rodape
svgCloudGen :: Int -> Int -> [Int] -> String
svgCloudGen w h dataset =
        "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" ++
        "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n" ++
        (svgViewBox w h) ++
        (concat (svgBubbleGen w h dataset)) ++ 
        (geraTexto ((fromIntegral w/2) - (retornaRaio (proxRaio dataset)*0.10)) (fromIntegral h/2) ("Teste bubble")) ++
        "</svg>\n"


-- Esta funcao deve gerar a lista de circulos em formato SVG.
-- A implementacao atual eh apenas um teste que gera um circulo posicionado no meio da figura.
-- TODO: Alterar essa funcao para usar os dados do dataset.
svgBubbleGen:: Int -> Int -> [Int] -> [String]
svgBubbleGen w h dataset = 
   [svgCircle ((fromIntegral w/2, fromIntegral h/2), (retornaRaio (dataset))*0.10)(255,0,5), svgCircle (((fromIntegral w/2)+((retornaRaio (dataset))*0.10)+(retornaRaio (proxRaio dataset))*0.10, fromIntegral h/2), (retornaRaio (proxRaio dataset))*0.10)(123,250,215)]

-- Dar um jeito de receber a lista de Strings como parametro, montando ela em outra funcao, recursiva se der.


-- Temos que fazer o svgBubbleGen chamar-se recursivamente enquanto houverem dados no dataset;
-- adicionar um IF para verificar quando eh a primeira chamada, talvez por algum id passado por parametro
-- para posicionar o primeiro circulo no meio do svg e os outros relativos a esse primeiro.


-- Retorna o numero de ocorrencias de uma palavra. Retorna 0 se a lista de entrada estiver vazia.
retornaRaio :: [Int] -> Float
retornaRaio [] = 0.0
retornaRaio dataset = fromIntegral (head dataset)

-- Retorna uma lista de inteiros sem o primeiro elemento da lista que entrou
proxRaio :: [Int] -> [Int]
proxRaio [] = []
proxRaio dataset = tail dataset

-- randomRIO (0, 255)

-- Gera string representando um circulo em SVG. A cor do circulo esta fixa.
-- TODO: Alterar esta funcao para mostrar um circulo de uma cor fornecida como parametro.
svgCircle :: Circle -> Color -> String
svgCircle ((x,y),raio) (r,g,b)= printf "<circle cx=\"%f\" cy=\"%f\" r=\"%f\" fill=\"rgb(%d,%d,%d)\" />\n" x y raio r g b

geraTexto :: Float -> Float -> String -> String
geraTexto x y dataset = printf "<text x=\"%f\"  y=\"%f\" style=\"stroke:none; fill:#000000;\">%s</text>" x y dataset


-- Configura o viewBox da imagem e coloca retangulo branco no fundo
svgViewBox :: Int -> Int -> String
svgViewBox w h =
        printf  "<svg width=\"%d\" height=\"%d\" viewBox=\"0 0 %d %d\"" w h w h ++
                " version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n" ++
        printf "<rect x=\"0\" y=\"0\" width=\"%d\" height=\"%d\" style=\"fill:white;\"/>\n" w h
